<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { NAvatar, NButton, NCard, NCarousel, NDivider, NInput, NRate, NTag, useMessage } from 'naive-ui';
import { addGameReview, fetchGameDetail, fetchGameReviews, fetchUserGames } from '@/service/api/game';
import { fetchUserInfo } from '@/service/api/user';
import { useAuthStore } from '@/store/modules/auth';
const route = useRoute();

const gameTypes = ref<Array<{ category: string; games: any[] }>>([]);
const expandedTypeIds = ref<string[]>([]);
const selectedGameId = ref<number | null>(null);
const message = useMessage();

const reviews = ref<any[]>([]);
const reviewContent = ref('');
const reviewRating = ref(5);
const reviewLoading = ref(false);

const authStore = useAuthStore();
const currentGameData = ref<any>(null);
const developer = ref('');
const instructions = ref('');

onMounted(async () => {
  try {
    const userId = authStore.userInfo.userId;
    if (!userId) {
      message?.error('未获取到用户ID，请重新登录');
      return;
    }
    const res = await fetchUserGames(userId);
    const rawList = Array.isArray(res) ? res : (res?.data ?? []);
    if (!Array.isArray(rawList)) {
      console.error('后端返回数据不是数组，实际为：', rawList, '原始res:', res);
      message?.error('后端返回数据格式异常');
      return;
    }
    // 自动分组：将用户拥有的游戏按gameCategory分组
    const groupMap = new Map<string, any[]>();
    for (const game of rawList) {
      if (game.gameCategory) {
        if (!groupMap.has(game.gameCategory)) groupMap.set(game.gameCategory, []);
        groupMap.get(game.gameCategory)!.push(game);
      }
    }
    const grouped = Array.from(groupMap.entries()).map(([category, games]) => ({ category, games }));
    gameTypes.value = grouped;

    // 检查是否有高亮参数（只有新购买的游戏才有highlight参数）
    const highlightGameId = route.query.highlight ? Number(route.query.highlight) : null;

    if (gameTypes.value.length > 0) {
      if (highlightGameId) {
        // 查找高亮的游戏并选中，显示欢迎提示
        let foundGame = false;
        for (const type of gameTypes.value) {
          const game = type.games.find(g => g.gameId === highlightGameId);
          if (game) {
            expandedTypeIds.value.push(type.category);
            selectedGameId.value = game.gameId;
            foundGame = true;
            message?.success(`欢迎体验新购买的游戏：${game.gameName}`);
            break;
          }
        }
        if (!foundGame) {
          // 如果没找到高亮游戏，使用默认选择
          expandedTypeIds.value.push(gameTypes.value[0].category);
          if (Array.isArray(gameTypes.value[0].games) && gameTypes.value[0].games.length > 0) {
            selectedGameId.value = gameTypes.value[0].games[0].gameId;
          }
        }
      } else {
        // 默认选择第一个游戏
        expandedTypeIds.value.push(gameTypes.value[0].category);
        if (Array.isArray(gameTypes.value[0].games) && gameTypes.value[0].games.length > 0) {
          selectedGameId.value = gameTypes.value[0].games[0].gameId;
        } else {
          console.warn('第一个类型下没有游戏，或games字段不是数组', gameTypes.value[0]);
        }
      }
    } else {
      console.warn('gameTypes为空', gameTypes.value);
    }
  } catch (err) {
    console.error('获取游戏数据失败:', err);
    message?.error('获取游戏数据失败');
  }
});

const toggleType = (category: string) => {
  const idx = expandedTypeIds.value.indexOf(category);
  if (idx > -1) {
    expandedTypeIds.value.splice(idx, 1);
  } else {
    expandedTypeIds.value.push(category);
  }
};

const openDetail = (category: string, gameId: number) => {
  if (!expandedTypeIds.value.includes(category)) {
    expandedTypeIds.value.push(category);
  }
  selectedGameId.value = gameId;
};

const currentGame = computed(() => {
  for (const type of gameTypes.value) {
    if (Array.isArray(type.games)) {
      const game = type.games.find(g => g.gameId === selectedGameId.value);
      if (game) return game;
    }
  }
  return null;
});

// 加载评论并补充用户名
async function loadReviews(gameId: number) {
  try {
    const res = await fetchGameReviews(gameId);
    const list = Array.isArray(res) ? res : (res?.data ?? []);
    // 批量查用户名
    const userIdSet = Array.from(new Set(list.map(item => item.userId || item.user_id)));
    const userMap: Record<string, string> = {};
    await Promise.all(
      userIdSet.map(async uid => {
        if (!uid) return;
        try {
          const { data } = await fetchUserInfo(uid);
          if (data && data.username) userMap[uid] = data.username;
        } catch {}
      })
    );
    // 合并用户名
    reviews.value = list.map(item => ({
      ...item,
      username: userMap[item.userId || item.user_id] || `用户${item.userId || item.user_id}`
    }));
  } catch (err) {
    console.error('获取评论失败:', err);
    reviews.value = [];
  }
}

// 发表评论
async function submitReview() {
  if (!currentGame.value || !reviewContent.value.trim()) return;
  reviewLoading.value = true;
  try {
    // 获取当前登录用户ID
    const userId = Number(authStore.userInfo.userId);
    if (!userId) {
      message.error('未获取到用户ID，请重新登录');
      reviewLoading.value = false;
      return;
    }
    const reviewData = {
      gameId: currentGame.value.gameId,
      userId,
      comment: reviewContent.value, // 字段名改为comment
      rating: reviewRating.value
    };
    const res = await addGameReview(reviewData);
    reviewContent.value = '';
    reviewRating.value = 5;
    await loadReviews(currentGame.value.gameId);
    message.success('评论成功');
  } catch (err) {
    message.error('评论失败');
    console.error('评论失败:', err);
  } finally {
    reviewLoading.value = false;
  }
}

function highlightKeys(raw: string): string {
  if (!raw) return '';
  let text = raw;
  // 按长度降序排列，先替换多字符，避免 ESC 被拆分
  const keycapList = ['鼠标左键', '鼠标右键', 'ESC', '空格', 'E', 'W', 'A', 'S', 'D'];
  keycapList.forEach(key => {
    // 只替换未被keycap包裹的
    const reg = new RegExp(`(?<!<span class="keycap">)${key}(?!</span>)`, 'g');
    text = text.replace(reg, `<span class="keycap">${key}</span>`);
  });
  // 换行转为<br>
  text = text.replace(/\n/g, '<br>');
  return text;
}

async function loadExtraInfo(game: any) {
  developer.value = '';
  instructions.value = '';
  if (game && game.pic) {
    const base = game.pic.endsWith('/') ? game.pic : `${game.pic}/`;
    // 读取开发商
    try {
      const devRes = await fetch(`${base}assets/main/developer`);
      developer.value = await devRes.text();
    } catch (e) {
      developer.value = '未知开发商';
      console.log('[GameLibrary] developer加载失败:', e);
    }
    // 读取操作说明
    try {
      const insRes = await fetch(`${base}assets/main/Instructions`);
      const rawText = await insRes.text();
      instructions.value = highlightKeys(rawText);
    } catch (e) {
      instructions.value = '暂无操作说明';
      console.log('[GameLibrary] Instruction加载失败:', e);
    }
  }
}

watch(currentGame, async val => {
  if (val && val.gameId) {
    loadReviews(val.gameId);
    // 查询详情
    try {
      const detailRes = await fetchGameDetail(val.gameId);
      const detail = detailRes?.data || {};
      currentGameData.value = { ...val, ...detail };
      await loadExtraInfo(currentGameData.value);
    } catch (e) {
      console.error('[GameLibrary] fetchGameDetail失败:', e);
      currentGameData.value = val;
      await loadExtraInfo(val);
    }
  } else {
    currentGameData.value = null;
    developer.value = '';
    instructions.value = '';
  }
});

const specialReviews = computed(() => reviews.value.filter(r => r.rating === 5));
const otherReviews = computed(() => reviews.value.filter(r => r.rating < 5));

function getCoverUrl(game: any) {
  if (game && game.pic) {
    const base = game.pic.endsWith('/') ? game.pic : `${game.pic}/`;
    return `${base}assets/main/game-logo.svg`;
  }
  return '@/assets/imgs/game-logo.svg';
}

function getSliderImages(game: any) {
  if (game && game.pic) {
    const base = game.pic.endsWith('/') ? game.pic : `${game.pic}/`;
    const imgs = Array.from({ length: 3 }, (_, i) => `${base}assets/main/img/slider${i + 1}.png`);
    return imgs;
  }
  return [];
}

// 新增跳转方法
function goToGame(game: any) {
  if (game && game.pic) {
    const base = game.pic.endsWith('/') ? game.pic : `${game.pic}/`;
    window.open(`${base}index.html`, '_blank');
  }
}
</script>

<template>
  <div class="gamelibrary-container">
    <!-- 左侧类型下拉菜单 -->
    <aside class="type-list">
      <ul>
        <li v-for="type in gameTypes" :key="type.category">
          <div class="type-header" @click="toggleType(type.category)">
            <span>{{ type.category }}</span>
            <span class="arrow" :class="{ open: expandedTypeIds.includes(type.category) }">&#9662;</span>
          </div>
          <ul v-show="expandedTypeIds.includes(type.category)" class="game-sub-list">
            <li
              v-for="game in type.games"
              :key="game.gameId"
              :class="{
                active: game.gameId === selectedGameId
              }"
              @click.stop="openDetail(type.category, game.gameId)"
            >
              {{ game.gameName }}
            </li>
          </ul>
        </li>
      </ul>
    </aside>
    <!-- 右侧详情区 -->
    <main v-if="currentGameData" class="game-detail-pane">
      <NCard class="game-detail-card" :content-style="{ padding: '0' }" hoverable>
        <!-- 移除调试信息 -->
        <!-- 游戏截图轮播放最上面 -->
        <div class="screenshots-carousel-16-9-wrapper">
          <NCarousel
            :key="currentGameData?.gameId"
            class="screenshots-carousel-16-9"
            show-arrow
            dot-type="line"
            :autoplay="true"
            :interval="4000"
          >
            <template v-for="(img, idx) in getSliderImages(currentGameData)" :key="idx">
              <div class="carousel-img-16-9">
                <img :src="img" :alt="currentGameData.gameName + '截图' + (idx + 1)" />
              </div>
            </template>
          </NCarousel>
        </div>
        <div class="header">
          <NAvatar :src="getCoverUrl(currentGameData)" size="large" round class="logo" />
          <div>
            <h1 class="game-title">{{ currentGameData.gameName || '游戏详情' }}</h1>
            <div class="game-tags">
              <NTag type="info" size="small" style="margin-right: 8px">ID: {{ currentGameData.gameId }}</NTag>
              <NTag type="primary" size="small">{{ currentGameData.gameCategory }}</NTag>
            </div>
          </div>
        </div>
        <NDivider style="margin: 16px 0" />
        <div class="info">
          <div class="info-row">
            <span>开发商：</span>
            <span class="desc">{{ developer }}</span>
          </div>
          <div class="info-row">
            <span>游戏状态：</span>
            <NTag type="success" size="small">已购买</NTag>
          </div>
          <div class="info-row">
            <span>游戏价格：</span>
            <span class="desc price">¥{{ currentGameData.price }}</span>
          </div>
          <div class="info-row">
            <span>游戏评分：</span>
            <span class="desc">
              <NRate :value="currentGameData.score" readonly allow-half size="small" style="margin-right: 8px" />
              <span style="color: #faad14; font-weight: 600">{{ currentGameData.score }}</span>
            </span>
          </div>
        </div>
        <div class="actions">
          <NButton
            type="primary"
            size="large"
            class="start-btn"
            :style="{ transition: 'all .2s' }"
            @click="goToGame(currentGameData)"
          >
            开始游戏
          </NButton>
        </div>
        <NDivider style="margin: 16px 0" />
        <!-- 游戏详细介绍模块 -->
        <section class="game-section">
          <h2 class="section-title">详细简介</h2>
          <p class="section-content">{{ currentGameData.description }}</p>
        </section>
        <!-- 游戏操作说明模块 -->
        <section class="game-section">
          <h2 class="section-title">游戏操作说明</h2>
          <div class="section-content" v-html="instructions"></div>
        </section>
        <!-- 游戏评论系统模块 -->
        <section class="game-section">
          <h2 class="section-title">游戏评论</h2>
          <div class="comments">
            <template v-if="specialReviews.length">
              <div class="comment-group-title">特别好评</div>
              <div v-for="item in specialReviews" :key="item.id" class="comment-item">
                <NAvatar :size="32" style="margin-right: 8px; vertical-align: middle" />
                <b>{{ item.username }}：</b>
                <NRate :value="item.rating" readonly size="small" style="margin: 0 8px" />
                <span>{{ item.comment }}</span>
              </div>
            </template>
            <template v-if="otherReviews.length">
              <div class="comment-group-title">其他评论</div>
              <div v-for="item in otherReviews" :key="item.id" class="comment-item">
                <NAvatar :size="32" style="margin-right: 8px; vertical-align: middle" />
                <b>{{ item.username }}：</b>
                <NRate :value="item.rating" readonly size="small" style="margin: 0 8px" />
                <span>{{ item.comment }}</span>
              </div>
            </template>
            <div v-if="!specialReviews.length && !otherReviews.length" class="comment-item">暂无评论</div>
            <div class="comment-form">
              <NInput
                v-model:value="reviewContent"
                type="textarea"
                class="comment-input"
                placeholder="请输入你的评论..."
                :autosize="{ minRows: 2, maxRows: 4 }"
                :disabled="reviewLoading"
                show-count
                maxlength="200"
                clearable
                :style="{ marginBottom: '8px' }"
              />
              <div style="margin: 8px 0; display: flex; align-items: center; gap: 8px">
                <label>评分：</label>
                <NRate v-model:value="reviewRating" :disabled="reviewLoading" />
              </div>
              <NButton
                type="primary"
                class="comment-btn"
                :disabled="reviewLoading || !reviewContent.trim()"
                :loading="reviewLoading"
                secondary
                style="transition: all 0.2s"
                @click="submitReview"
              >
                发表评论
              </NButton>
            </div>
          </div>
        </section>
      </NCard>
    </main>
  </div>
</template>

<style scoped>
.gamelibrary-container {
  display: flex;
  height: 100vh;
  min-height: 0;
  background: var(--background-color);
  font-family: var(--font-family-main);
  border-radius: 0;
  box-shadow: none;
  margin: 0;
  max-width: none;
  overflow: auto;
}
.type-list {
  width: 260px;
  background: #f5f7fa;
  color: var(--text-color-main);
  border-right: 1px solid var(--border-color);
  overflow-y: auto;
  overflow-x: hidden;
  box-shadow: none;
  border-radius: 0;
  margin: 0;
  height: 100%;
}
.type-list ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.type-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 18px 16px;
  cursor: pointer;
  border-bottom: 1px solid #e0e6ed;
  font-size: 18px;
  font-weight: 700;
  background: #eaf1fb;
  box-shadow: 0 2px 8px #1976d211;
  transition:
    background 0.2s,
    color 0.2s,
    font-weight 0.2s,
    box-shadow 0.2s,
    transform 0.1s;
  letter-spacing: 0.5px;
  user-select: none;
  border-radius: 16px 16px 0 0;
}
.type-header:hover {
  background: #d2e6fa;
  color: #1976d2;
  font-weight: 800;
  box-shadow: 0 4px 16px #1976d233;
  transform: translateX(2px) scale(1.03);
}
.type-header:active {
  background: #e6f0fa;
  color: var(--primary-color-hover);
  font-weight: 700;
  box-shadow: var(--shadow-main);
  transform: scale(0.98);
}
.arrow {
  transition:
    transform 0.2s,
    color 0.2s;
  font-size: 13px;
  color: #bbb;
}
.arrow.open {
  transform: rotate(180deg);
  color: var(--primary-color);
}
.game-sub-list {
  background: #fff;
  padding: 8px 0 8px 0;
  border-radius: 0 0 16px 16px;
  margin: 0 8px 12px 8px;
  box-shadow: 0 2px 12px #1976d211;
  border: 1px solid #e0e6ed;
  overflow: visible;
}
.game-sub-list li {
  padding: 13px 28px;
  cursor: pointer;
  border-bottom: 1px solid #f0f0f0;
  font-size: 15px;
  color: #4a5a6a;
  background: transparent;
  transition:
    background 0.2s,
    color 0.2s,
    font-weight 0.2s,
    box-shadow 0.2s,
    transform 0.1s;
  border-left: 3px solid transparent;
  border-radius: 8px;
  user-select: none;
  letter-spacing: 0.2px;
  margin: 4px 8px;
}
.game-sub-list li:hover {
  background: #eaf1fb;
  color: #1976d2;
  font-weight: 700;
  box-shadow: 0 2px 8px #1976d233;
  transform: translateX(4px) scale(1.04);
}
.game-sub-list li:active {
  background: #d2e6fa;
  color: var(--primary-color-hover);
  font-weight: 700;
  box-shadow: var(--shadow-main);
  transform: scale(0.97);
}
.game-sub-list li.active {
  background: #d2e6fa;
  color: #1976d2;
  border-left: 3px solid #1976d2;
  font-weight: 800;
  box-shadow: 0 4px 16px #1976d233;
}

.game-detail-pane {
  flex: 1 1 0%;
  min-width: 0;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 0;
  background: var(--background-color);
  /* 不强制高度，内容自适应 */
}
.game-detail-card {
  background: var(--background-color);
  border-radius: var(--radius-card);
  padding: 40px 48px 32px 48px;
  box-shadow: var(--shadow-main);
  width: 100%;
  display: block;
  transition: box-shadow 0.2s;
}
.game-detail-card:hover {
  box-shadow: 0 8px 32px #1976d244;
}
.header {
  display: flex;
  align-items: center;
  gap: var(--gap-md);
  margin-bottom: var(--gap-md);
}
.logo {
  width: 56px;
  height: 56px;
  border-radius: 8px;
  object-fit: cover;
  background: #f0f0f0;
}
.game-title {
  font-size: var(--font-size-title);
  font-weight: 700;
  color: var(--primary-color);
  margin-bottom: 4px;
}
.game-tags {
  display: flex;
  gap: 8px;
}
.info {
  margin-bottom: var(--gap-md);
}
.info-row {
  display: flex;
  justify-content: space-between;
  margin-bottom: 8px;
  font-size: var(--font-size-main);
}
.desc {
  color: var(--text-color-sub);
  max-width: 60vw;
  text-align: right;
}
.actions {
  display: flex;
  justify-content: center;
  margin-bottom: var(--gap-md);
}
.start-btn {
  background: var(--primary-gradient);
  color: #fff;
  border: none;
  border-radius: 6px;
  padding: 10px 32px;
  font-size: var(--font-size-main);
  cursor: pointer;
  font-weight: 600;
  transition:
    background 0.2s,
    transform 0.15s;
  box-shadow: 0 2px 8px #1976d233;
}
.start-btn:hover {
  background: linear-gradient(90deg, #1565c0 0%, #67b1fb 100%);
  transform: scale(1.04);
}
.start-btn:active {
  background: linear-gradient(90deg, #1976d2 0%, #1565c0 100%);
  transform: scale(0.97);
}
.game-section {
  margin-top: var(--gap-lg);
  margin-bottom: var(--gap-lg);
  padding-bottom: var(--gap-sm);
  border-bottom: 1px solid var(--border-color);
}
.section-title {
  font-size: var(--font-size-title);
  font-weight: 600;
  margin-bottom: 12px;
  color: var(--text-color-main);
}
.section-content {
  font-size: var(--font-size-main);
  color: var(--text-color-sub);
  margin-bottom: 8px;
}
.screenshots {
  display: flex;
  gap: var(--gap-md);
  margin-bottom: 8px;
}
.screenshot-img {
  width: 120px;
  height: 80px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid #eee;
  background: #fafafa;
  transition:
    box-shadow 0.2s,
    transform 0.15s;
}
.screenshot-img:hover {
  box-shadow: 0 4px 16px #1976d233;
  transform: scale(1.05);
}
.screenshots-carousel {
  margin-bottom: 8px;
  border-radius: 12px;
  box-shadow: 0 2px 8px #1976d233;
  background: #fafafa;
}
.screenshots-carousel-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
}
.full-width-carousel {
  width: 100%;
  max-width: 100%;
}
.screenshots-carousel-wrapper {
  width: 100%;
  margin-left: 0;
  margin-right: 0;
}
.rank-table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 8px;
}
.rank-table th,
.rank-table td {
  border: 1px solid var(--border-color);
  padding: 6px 12px;
  text-align: center;
}
.rank-table th {
  background: var(--secondary-color);
  color: var(--text-color-light);
}
.comments {
  margin-top: 8px;
}
.comment-item {
  background: var(--card-bg);
  border-radius: 6px;
  padding: 12px 16px;
  margin-bottom: 16px;
  color: var(--text-color-main);
  display: flex;
  align-items: center;
  gap: 16px;
  transition:
    box-shadow 0.2s,
    transform 0.15s;
  font-size: 1.08em;
  line-height: 1.7;
}
.comment-item:hover {
  box-shadow: 0 2px 8px #1976d233;
  transform: scale(1.01);
}
.comment-input {
  width: 100%;
  min-height: 48px;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  margin-bottom: 8px;
  padding: 8px;
  font-size: var(--font-size-sub);
  resize: vertical;
}
.comment-btn {
  background: var(--primary-gradient);
  color: #fff;
  border: none;
  border-radius: 6px;
  padding: 8px 24px;
  font-size: var(--font-size-sub);
  cursor: pointer;
  font-weight: 500;
  transition:
    background 0.2s,
    transform 0.15s;
  box-shadow: 0 2px 8px #1976d233;
}
.comment-btn:hover {
  background: linear-gradient(90deg, #1565c0 0%, #67b1fb 100%);
  transform: scale(1.04);
}
.comment-btn:active {
  background: linear-gradient(90deg, #1976d2 0%, #1565c0 100%);
  transform: scale(0.97);
}
.screenshots-carousel-16-9-wrapper {
  width: 100%;
  position: relative;
  margin-bottom: 24px;
}
.screenshots-carousel-16-9 {
  width: 100%;
  /* 高度由内部撑开 */
}
.carousel-img-16-9 {
  position: relative;
  width: 100%;
  padding-top: 56.25%; /* 16:9 */
  overflow: hidden;
  border-radius: 12px;
}
.carousel-img-16-9 img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 12px;
  display: block;
}
.keycap {
  display: inline-block;
  min-width: 1.8em;
  padding: 0 0.5em;
  margin: 0 2px;
  border: 1.5px solid #1976d2;
  border-radius: 6px;
  background: #f5f7fa;
  color: #1976d2;
  font-weight: 600;
  font-size: 1em;
  line-height: 1.7;
  text-align: center;
  box-shadow: 0 1px 2px #1976d211;
  user-select: none;
  vertical-align: middle;
  transition:
    border-color 0.2s,
    background 0.2s;
}
.keycap:hover {
  border-color: #1565c0;
  background: #e6f0fa;
}
.comment-group-title {
  font-size: 1.1em;
  font-weight: 700;
  color: #1976d2;
  margin: 16px 0 8px 0;
  letter-spacing: 1px;
}
.achievements-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 32px;
  margin: 16px 0 8px 0;
  padding: 0 32px;
  /* 让两侧和中间间距一致 */
}
.achievement-box {
  flex: 1 1 0;
  min-width: 0;
  max-width: 260px;
  box-sizing: border-box;
  background: #fff;
  border: 2.5px solid #1976d2;
  border-radius: 0 16px 0 16px;
  position: relative;
  padding: 18px 18px 14px 18px;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 12px #1976d211;
  transition:
    border-color 0.2s,
    box-shadow 0.2s;
  text-align: center;
  flex-basis: calc((100% - 2 * 32px - 2 * 32px) / 3); /* 3个框+4个间距 */
}
.achievement-box:not(:last-child) {
  /* 间距由gap控制 */
}
.achievement-box::before {
  content: '';
  position: absolute;
  left: -2.5px;
  top: -2.5px;
  width: 0;
  height: 0;
  border-top: 18px solid #1976d2;
  border-right: 18px solid transparent;
  border-radius: 0;
}
.achievement-box::after {
  content: '';
  position: absolute;
  right: -2.5px;
  bottom: -2.5px;
  width: 0;
  height: 0;
  border-bottom: 18px solid #1976d2;
  border-left: 18px solid transparent;
  border-radius: 0;
}
.achievement-title {
  font-size: 1.1em;
  font-weight: 700;
  color: #1976d2;
  margin-bottom: 6px;
}
.achievement-desc {
  font-size: 0.98em;
  color: #555;
  opacity: 0.95;
}
</style>
